package org.dromara.nursing.service.impl;

import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.dromara.nursing.domain.bo.BedInfoBo;
import org.dromara.nursing.domain.vo.BedInfoVo;
import org.dromara.nursing.domain.BedInfo;
import org.dromara.nursing.mapper.BedInfoMapper;
import org.dromara.nursing.service.IBedInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.util.ReflectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;

/**
 * 床位管理Service业务层处理
 *
 * @author Xue
 * @date 2025-04-09
 */
@RequiredArgsConstructor
@Service
public class BedInfoServiceImpl implements IBedInfoService {

    private final BedInfoMapper baseMapper;
    private static final Logger log = LoggerFactory.getLogger(BedInfoServiceImpl.class);
    @Autowired
    private ApplicationContext applicationContext;

    /**
     * 查询床位管理
     *
     * @param bedId 主键
     * @return 床位管理
     */
    @Override
    public BedInfoVo queryById(Long bedId){
        return baseMapper.selectVoById(bedId);
    }

    /**
     * 分页查询床位管理列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 床位管理分页列表
     */
    @Override
    public TableDataInfo<BedInfoVo> queryPageList(BedInfoBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<BedInfo> lqw = buildQueryWrapper(bo);
        Page<BedInfoVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的床位管理列表
     *
     * @param bo 查询条件
     * @return 床位管理列表
     */
    @Override
    public List<BedInfoVo> queryList(BedInfoBo bo) {
        LambdaQueryWrapper<BedInfo> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<BedInfo> buildQueryWrapper(BedInfoBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<BedInfo> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(BedInfo::getBedId);

        // 添加房间ID查询条件
        lqw.eq(bo.getRoomId() != null, BedInfo::getRoomId, bo.getRoomId());

        // 保留原有的房间号查询条件
        lqw.eq(StringUtils.isNotBlank(bo.getRoomNumber()), BedInfo::getRoomNumber, bo.getRoomNumber());

        // 保留原有的床位号查询条件
        lqw.eq(StringUtils.isNotBlank(bo.getBedNumber()), BedInfo::getBedNumber, bo.getBedNumber());

        // 保留原有的老人姓名查询条件
        lqw.like(StringUtils.isNotBlank(bo.getElderName()), BedInfo::getElderName, bo.getElderName());

        // 添加床位状态查询条件
        lqw.eq(StringUtils.isNotBlank(bo.getBedStatus()), BedInfo::getBedStatus, bo.getBedStatus());

        // 记录查询条件
        log.info("床位查询条件: roomId={}, roomNumber={}, bedNumber={}, bedStatus={}, elderName={}",
            bo.getRoomId(), bo.getRoomNumber(), bo.getBedNumber(), bo.getBedStatus(), bo.getElderName());

        return lqw;
    }

    /**
     * 新增床位管理
     *
     * @param bo 床位管理
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(BedInfoBo bo) {
        try {
            BedInfo add = MapstructUtils.convert(bo, BedInfo.class);
            validEntityBeforeSave(add);

            // 确保elderName不为null，如果为空则设置为空字符串
            if (add.getElderName() == null) {
                add.setElderName("");
            }

            log.info("正在创建床位: 房间号={}, 床位号={}", add.getRoomNumber(), add.getBedNumber());
            boolean flag = baseMapper.insert(add) > 0;
            if (flag) {
                bo.setBedId(add.getBedId());
                log.info("床位创建成功: bedId={}", add.getBedId());
            } else {
                log.warn("床位创建失败: roomNumber={}, bedNumber={}", add.getRoomNumber(), add.getBedNumber());
            }
            return flag;
        } catch (Exception e) {
            log.error("床位创建异常", e);
            return false;
        }
    }

    /**
     * 修改床位管理
     *
     * @param bo 床位管理
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(BedInfoBo bo) {
        try {
            log.info("开始修改床位信息: {}", bo.getBedNumber());

            // 获取原床位信息
            BedInfo oldBed = baseMapper.selectById(bo.getBedId());
            if (oldBed == null) {
                log.warn("床位不存在: bedId={}", bo.getBedId());
                return false;
            }

            // 转换BO为实体
            BedInfo update = MapstructUtils.convert(bo, BedInfo.class);
            validEntityBeforeSave(update);

            // 如果床位状态发生变化
            boolean statusChanged = !oldBed.getBedStatus().equals(update.getBedStatus());

            boolean result = baseMapper.updateById(update) > 0;
            if (result) {
                log.info("床位信息修改成功: bedId={}, 状态: {}", update.getBedId(), update.getBedStatus());

                // 如果床位状态发生变化，需要更新房间可用床位数和状态
                if (statusChanged) {
                    updateRoomAvailableBeds(update.getRoomId());
                }

                return true;
            } else {
                log.warn("床位信息修改失败: bedId={}", bo.getBedId());
                return false;
            }
        } catch (Exception e) {
            log.error("修改床位信息异常: ", e);
            return false;
        }
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(BedInfo entity){
        // 床位状态校验
        if (StringUtils.isEmpty(entity.getBedStatus())) {
            entity.setBedStatus("空闲");
        }

        // 如果床位状态为"空闲"，则清除老人信息
        if ("空闲".equals(entity.getBedStatus())) {
            entity.setElderId(null);
            entity.setElderName("");
        }

        // 如果床位状态为"已占用"，确保有老人信息
        if ("已占用".equals(entity.getBedStatus()) && (entity.getElderId() == null || StringUtils.isEmpty(entity.getElderName()))) {
            throw new RuntimeException("床位状态为已占用时，必须指定老人信息");
        }
    }

    /**
     * 更新房间可用床位数
     *
     * @param roomId 房间ID
     */
    private void updateRoomAvailableBeds(Long roomId) {
        try {
            log.info("开始更新房间[{}]可用床位数", roomId);

            // 查询空闲床位数
            LambdaQueryWrapper<BedInfo> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(BedInfo::getRoomId, roomId);
            queryWrapper.eq(BedInfo::getBedStatus, "空闲");

            long availableBeds = baseMapper.selectCount(queryWrapper);
            log.info("房间[{}]空闲床位数: {}", roomId, availableBeds);

            // 获取房间信息实体类的全限定名
            String roomInfoClassName = "org.dromara.nursing.domain.RoomInfo";

            // 获取房间信息服务类的Bean
            String roomInfoServiceBeanName = "roomInfoServiceImpl";
            Object roomInfoService = applicationContext.getBean(roomInfoServiceBeanName);

            if (roomInfoService != null) {
                try {
                    // 获取更新方法
                    Method updateAvailableBedsMethod = roomInfoService.getClass().getDeclaredMethod("updateAvailableBeds", Long.class);

                    // 设置方法可访问
                    updateAvailableBedsMethod.setAccessible(true);

                    // 调用方法
                    updateAvailableBedsMethod.invoke(roomInfoService, roomId);
                    log.info("通过反射调用更新房间可用床位数方法成功");
                } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                    log.error("通过反射调用更新房间可用床位数方法失败: {}", e.getMessage());

                    // 获取RoomInfoMapper
                    Class<?> mapperClass = Class.forName("org.dromara.nursing.mapper.RoomInfoMapper");
                    Object roomInfoMapper = applicationContext.getBean(mapperClass);

                    if (roomInfoMapper != null) {
                        try {
                            // 查询房间信息
                            Method selectByIdMethod = roomInfoMapper.getClass().getMethod("selectById", Serializable.class);
                            Object roomInfo = selectByIdMethod.invoke(roomInfoMapper, roomId);

                            if (roomInfo != null) {
                                // 设置可用床位数
                                Class<?> roomInfoClass = Class.forName(roomInfoClassName);
                                Method setAvailableBedsMethod = roomInfoClass.getMethod("setAvailableBeds", Long.class);
                                setAvailableBedsMethod.invoke(roomInfo, availableBeds);

                                // 获取总床位数
                                Method getBedCountMethod = roomInfoClass.getMethod("getBedCount");
                                Object bedCount = getBedCountMethod.invoke(roomInfo);

                                // 设置房间状态
                                Method setRoomStatusMethod = roomInfoClass.getMethod("setRoomStatus", String.class);

                                // 更新房间状态
                                if (availableBeds <= 0) {
                                    setRoomStatusMethod.invoke(roomInfo, "已满");
                                } else if (availableBeds < ((Long) bedCount)) {
                                    setRoomStatusMethod.invoke(roomInfo, "部分可用");
                                } else {
                                    setRoomStatusMethod.invoke(roomInfo, "可用");
                                }

                                // 更新房间信息
                                Method updateByIdMethod = roomInfoMapper.getClass().getMethod("updateById", Object.class);
                                updateByIdMethod.invoke(roomInfoMapper, roomInfo);

                                log.info("手动更新房间可用床位数成功");
                            }
                        } catch (Exception ex) {
                            log.error("手动更新房间可用床位数失败: {}", ex.getMessage());
                        }
                    }
                }
            } else {
                log.error("获取房间信息服务Bean失败");
            }
        } catch (Exception e) {
            log.error("更新房间可用床位数异常: {}", e.getMessage());
        }
    }

    /**
     * 校验并批量删除床位管理信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        try {
            log.info("开始删除床位记录，ids: {}", ids);

            if (isValid) {
                // 检查床位是否已被占用
                for (Long id : ids) {
                    BedInfo bedInfo = baseMapper.selectById(id);
                    if (bedInfo != null && "已占用".equals(bedInfo.getBedStatus())) {
                        log.warn("床位[{}]已被占用，不能删除", bedInfo.getBedNumber());
                        return false;
                    }
                }
            }

            int rows = baseMapper.deleteBatchIds(ids);
            boolean success = rows > 0;
            log.info("删除床位记录结果: {}, 影响行数: {}", success, rows);
            return success;
        } catch (Exception e) {
            log.error("删除床位记录异常", e);
            return false;
        }
    }

    /**
     * 获取基础Mapper对象
     *
     * @return BedInfoMapper
     */
    @Override
    public BedInfoMapper getBaseMapper() {
        return baseMapper;
    }
}
